home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsconsist / fsconsistIOClient.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  14.9 KB  |  528 lines

  1. /* 
  2.  * fsIOClient.c --
  3.  *
  4.  *    Routines to handle the client lists at the I/O handle level.  
  5.  *    The I/O handle client list is needed for cache consistency and to
  6.  *    verify that client's are valid.  The routines here add and remove
  7.  *    clients.
  8.  *    (Note that fsCacheConsist.c has routines which also use the client
  9.  *    list on the I/O handle, but those routines are specific to files.)
  10.  *
  11.  *    A master list of clients is also kept here to simplify cleaning
  12.  *    up after crashed clients.  Periodically this master list is checked
  13.  *    and the file state for dead clients is cleaned up.
  14.  *
  15.  * Copyright 1987 Regents of the University of California
  16.  * All rights reserved.
  17.  * Permission to use, copy, modify, and distribute this
  18.  * software and its documentation for any purpose and without
  19.  * fee is hereby granted, provided that the above copyright
  20.  * notice appear in all copies.  The University of California
  21.  * makes no representations about the suitability of this
  22.  * software for any purpose.  It is provided "as is" without
  23.  * express or implied warranty.
  24.  */
  25.  
  26. #ifndef lint
  27. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsconsist/fsconsistIOClient.c,v 9.7 92/08/10 17:24:02 mgbaker Exp $ SPRITE (Berkeley)";
  28. #endif not lint
  29.  
  30.  
  31. #include <sprite.h>
  32. #include <fs.h>
  33. #include <fsutil.h>
  34. #include <fsio.h>
  35. #include <fsconsist.h>
  36. #include <fsStat.h>
  37. #include <stdlib.h>
  38. #include <rpc.h>
  39.  
  40. #include <stdio.h>
  41. /*
  42.  * A master list of clients of this host.  This is maintained here and
  43.  * consulted periodically in order to be able to clean up after dead clients.
  44.  */
  45. static List_Links masterClientListHdr;
  46. static List_Links *masterClientList;
  47.  
  48. typedef struct {
  49.     List_Links    links;
  50.     int        clientID;
  51. } ClientItem;
  52.  
  53. static Sync_Lock clientLock;
  54. #define LOCKPTR (&clientLock)
  55.  
  56.  
  57. /*
  58.  * ----------------------------------------------------------------------------
  59.  *
  60.  * Fsconsist_ClientInit --
  61.  *
  62.  *    Initialize the master list of clients for this server.
  63.  *
  64.  * Results:
  65.  *    None.
  66.  *
  67.  * Side effects:
  68.  *    List_Init.
  69.  *
  70.  * ----------------------------------------------------------------------------
  71.  */
  72.  
  73. void
  74. Fsconsist_ClientInit()
  75. {
  76.     Sync_LockInitDynamic(&clientLock, "Fs:clientLock");
  77.     List_Init(&masterClientListHdr);
  78.     masterClientList = &masterClientListHdr;
  79. }
  80.  
  81.  
  82. /*
  83.  * ----------------------------------------------------------------------------
  84.  *
  85.  * Fsconsist_IOClientOpen --
  86.  *
  87.  *    Add the client to the set of clients doing I/O on a file.  This
  88.  *    increments reference counts due to the client.
  89.  *
  90.  * Results:
  91.  *    Returns a pointer to the client state just added.  This is used
  92.  *    by the file consistency routines, which set the cached boolean
  93.  *    and the openTimeStamp, but ignored by others.
  94.  *
  95.  * Side effects:
  96.  *    As well as adding the client to the set of clients for the I/O handle,
  97.  *    the client is recorded in the master list of clients (if it isn't
  98.  *    already there) so clients can be easily scavenged.
  99.  *
  100.  * ----------------------------------------------------------------------------
  101.  */
  102.  
  103. ENTRY Fsconsist_ClientInfo *
  104. Fsconsist_IOClientOpen(clientList, clientID, useFlags, cached)
  105.     List_Links    *clientList;    /* List of clients for the I/O handle. */
  106.     int        clientID;    /* The client who is opening the file. */
  107.     int        useFlags;    /* FS_READ | FS_WRITE | FS_EXECUTE */
  108.     Boolean    cached;        /* Boolean property recorded for client */
  109. {
  110.     register Fsconsist_ClientInfo *clientPtr;
  111.  
  112.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  113.     if (clientPtr->clientID == clientID) {
  114.         goto found;
  115.     }
  116.     }
  117.     INSERT_CLIENT(clientList, clientPtr, clientID);
  118. found:
  119.     clientPtr->cached = cached;
  120.     clientPtr->use.ref++;
  121.     if (useFlags & FS_WRITE) {
  122.     clientPtr->use.write++;
  123.     }
  124.     if (useFlags & FS_EXECUTE) {
  125.     clientPtr->use.exec++;
  126.     }
  127.  
  128.     /*
  129.      * Make sure the client is in the master list of all clients for this host.
  130.      */
  131.     Fsconsist_AddClient(clientID);
  132.     return(clientPtr);
  133. }
  134.  
  135. /*
  136.  * ----------------------------------------------------------------------------
  137.  *
  138.  * Fsconsist_IOClientAdd --
  139.  *
  140.  *    Add the client to the set of clients doing I/O on a file.  This
  141.  *    DOES NOT increment reference counts due to the client.  It is used
  142.  *    only for putting a client with a zero ref count onto the list during
  143.  *    fast recovery.  This happens if there's a client that has no open
  144.  *    references for the file, but still has cached blocks.
  145.  *
  146.  * Results:
  147.  *    None.
  148.  *
  149.  * Side effects:
  150.  *    Adds the client to the list.
  151.  *
  152.  * ----------------------------------------------------------------------------
  153.  */
  154.  
  155. ENTRY void
  156. Fsconsist_IOClientAdd(clientList, clientID, cached)
  157.     List_Links    *clientList;    /* List of clients for the I/O handle. */
  158.     int        clientID;    /* The client who is opening the file. */
  159.     Boolean    cached;        /* Boolean property recorded for client */
  160. {
  161.     register Fsconsist_ClientInfo *clientPtr;
  162.  
  163.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  164.     if (clientPtr->clientID == clientID) {
  165.         goto found;
  166.     }
  167.     }
  168.     INSERT_CLIENT(clientList, clientPtr, clientID);
  169. found:
  170.     clientPtr->cached = cached;
  171.     return;
  172. }
  173.  
  174. /*
  175.  * ----------------------------------------------------------------------------
  176.  *
  177.  * 
  178.  Fsconsist_IOClientReopen --
  179.  *
  180.  *    Add the client to the set of clients doing I/O on a file.  This
  181.  *    updates reference counts due to the client's reopen attempt.
  182.  *
  183.  * Results:
  184.  *    TRUE if the client was already listed.
  185.  *
  186.  * Side effects:
  187.  *    As well as adding the client to the set of clients for the I/O handle,
  188.  *    the client is recorded in the master list of clients (if it isn't
  189.  *    already there) so clients can be easily scavenged.
  190.  *
  191.  * ----------------------------------------------------------------------------
  192.  */
  193.  
  194. Boolean
  195. Fsconsist_IOClientReopen(clientList, clientID, usePtr)
  196.     List_Links    *clientList;    /* List of clients for the I/O handle. */
  197.     int        clientID;    /* The client who is opening the file. */
  198.     Fsio_UseCounts    *usePtr;    /* In - Client's usage of the object.
  199.                  * Out - difference between old client useage.
  200.                  *  This means that the summary use counts
  201.                  *  can be updated by adding the use counts
  202.                  *  left over in this structure after the
  203.                  *  reconciliation with the old state. */
  204. {
  205.     register Fsconsist_ClientInfo *clientPtr;
  206.     register Boolean found = FALSE;
  207.  
  208.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  209.     if (clientPtr->clientID == clientID) {
  210.         found = TRUE;
  211.         goto doit;
  212.     }
  213.     }
  214.     INSERT_CLIENT(clientList, clientPtr, clientID);
  215. doit:
  216.     clientPtr->use.ref += usePtr->ref;
  217.     clientPtr->use.write += usePtr->write;
  218.     clientPtr->use.exec += usePtr->exec;
  219.     /*
  220.      * Make sure the client is in the master list of all clients for this host.
  221.      */
  222.     Fsconsist_AddClient(clientID);
  223.     return(found);
  224. }
  225.  
  226. /*
  227.  * ----------------------------------------------------------------------------
  228.  *
  229.  * Fsconsist_IOClientClose --
  230.  *
  231.  *    Decrement the reference, executor and/or writer counts for the client 
  232.  *    for the given handle.  Note, we don't mess with the master list of
  233.  *    clients.  That gets cleaned up by Fsconsist_ClientScavenge.
  234.  *
  235.  * Results:
  236.  *    TRUE if there was a record that the client was using the file.
  237.  *    This is used to trap out invalid closes.
  238.  *
  239.  * Side effects:
  240.  *    The client list entry from the stream is removed.
  241.  *
  242.  * ----------------------------------------------------------------------------
  243.  *
  244.  */
  245. Boolean
  246. Fsconsist_IOClientClose(clientList, clientID, flags, cachePtr)
  247.     List_Links        *clientList;    /* List of clients for I/O handle */
  248.     int            clientID;    /* Host ID of client that had it open */
  249.     register int    flags;        /* Flags from the stream. */
  250.     Boolean        *cachePtr;    /* In/Out.  If TRUE on entry, this won't
  251.                      * delete the client list entry if
  252.                      * the entry's cached field is also
  253.                      * TRUE.  On return, this is the value
  254.                      * of the client's cached field. */
  255. {
  256.     register    Fsconsist_ClientInfo    *clientPtr;
  257.     register    Boolean        found = FALSE;
  258.  
  259.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  260.     if (clientPtr->clientID == clientID) {
  261.         found = TRUE;
  262.         break;
  263.     }
  264.     }
  265.     if (found) {
  266.     if ((clientPtr->use.ref < 0) || (clientPtr->use.write < 0) ||
  267.         (clientPtr->use.exec < 0)) {
  268.         printf("Fsconsist_IOClientClose: Values are bad at start:\n");
  269.         panic("Fsconsist_IOClientClose: client %d ref %d write %d exec %d\n",
  270.         clientPtr->clientID,
  271.         clientPtr->use.ref, clientPtr->use.write, clientPtr->use.exec);
  272.     }
  273.     clientPtr->use.ref--;
  274.     if (flags & FS_WRITE) {
  275.         clientPtr->use.write--;
  276.     }
  277.     if (flags & FS_EXECUTE) {
  278.         clientPtr->use.exec--;
  279.     }
  280.     if ((clientPtr->use.ref < 0) || (clientPtr->use.write < 0) ||
  281.         (clientPtr->use.exec < 0)) {
  282.         printf("This is (probably) a continuable panic.\n");
  283.         panic("Fsconsist_IOClientClose: client %d ref %d write %d exec %d\n",
  284.         clientPtr->clientID,
  285.         clientPtr->use.ref, clientPtr->use.write, clientPtr->use.exec);
  286.         clientPtr->use.exec = 0;
  287.     }
  288.     if ((!(*cachePtr) || !clientPtr->cached) &&
  289.         (clientPtr->use.ref == 0)) {
  290.         *cachePtr = clientPtr->cached;
  291.         if (!clientPtr->locked) {
  292.         /*
  293.          * Free up the client list entry if it is not locked
  294.          * due to an iteration through the client list.
  295.          */
  296.         REMOVE_CLIENT(clientPtr);
  297.         }
  298.     } else {
  299.         *cachePtr = clientPtr->cached;
  300.     }
  301.     }
  302.     return(found);
  303. }
  304.  
  305. /*
  306.  * ----------------------------------------------------------------------------
  307.  *
  308.  * Fsconsist_IOClientRemoveWriter --
  309.  *
  310.  *    Decrement the writer count for the client for the given handle.
  311.  *    This is done when a writer of a stream (for instance, a pipe)
  312.  *    becomes only a reader.
  313.  *
  314.  * Results:
  315.  *    TRUE if there was a record that the client was using the file.
  316.  *    This is used to trap out invalid closes.
  317.  *
  318.  * Side effects:
  319.  *    None.
  320.  *
  321.  * ----------------------------------------------------------------------------
  322.  *
  323.  */
  324. Boolean
  325. Fsconsist_IOClientRemoveWriter(clientList, clientID)
  326.     List_Links        *clientList;    /* List of clients for I/O handle */
  327.     int            clientID;    /* Host ID of client that had it open */
  328. {
  329.     register    Fsconsist_ClientInfo    *clientPtr;
  330.     register    Boolean        found = FALSE;
  331.  
  332.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  333.     if (clientPtr->clientID == clientID) {
  334.         found = TRUE;
  335.         break;
  336.     }
  337.     }
  338.     if (found) {
  339.     clientPtr->use.write--;
  340.     if (clientPtr->use.write < 0) {
  341.         panic("Fsconsist_IOClientRemoveWriter: client %d ref %d write %d exec %d\n",
  342.         clientPtr->clientID,
  343.         clientPtr->use.ref, clientPtr->use.write, clientPtr->use.exec);
  344.     }
  345.     }
  346.     return(found);
  347. }
  348.  
  349. /*
  350.  * ----------------------------------------------------------------------------
  351.  *
  352.  * Fsconsist_ClientScavenge --
  353.  *
  354.  *      Check the master list of clients for ones that have crashed.  If any
  355.  *    one has then we call Fsutil_RemoveClient to clean up the file state
  356.  *    associated with it.
  357.  *
  358.  *    NOT USED.  File servers let regular traffic, like consistency
  359.  *    call backs, detect failures.
  360.  *
  361.  * Results:
  362.  *    None.
  363.  *
  364.  * Side effects:
  365.  *    Calls FsClientRemove on dead clients, and nukes them from the
  366.  *    master client list.
  367.  *
  368.  * ----------------------------------------------------------------------------
  369.  *
  370.  */
  371. #ifdef notdef
  372. ENTRY void
  373. Fsconsist_ClientScavenge()
  374. {
  375.     register    ClientItem    *listPtr;
  376.  
  377.     LOCK_MONITOR;
  378.  
  379.     LIST_FORALL(masterClientList, (List_Links *)listPtr) {
  380.     if (listPtr->clientID != rpc_SpriteID && 
  381.         Recov_IsHostDown(listPtr->clientID)) {
  382.         Fsutil_RemoveClient(listPtr->clientID);
  383.     }
  384.     }
  385.  
  386.     UNLOCK_MONITOR;
  387. }
  388. #endif notdef
  389.  
  390. /*
  391.  * ----------------------------------------------------------------------------
  392.  *
  393.  * Fsconsist_IOClientKill --
  394.  *
  395.  *    Find and remove the given client in the list for the handle.  The
  396.  *    number of client references, writers, and executers is returned
  397.  *    so our caller can clean up the reference counts in the handle.
  398.  *
  399.  * Results:
  400.  *    *inUsePtr set to TRUE if the client has the file open, *writingPtr
  401.  *    set to TRUE if the client has the file open for writing, and 
  402.  *    *executingPtr set to TRUE if the client has the file open for
  403.  *    execution.
  404.  *    
  405.  * Side effects:
  406.  *    None.
  407.  *
  408.  * ----------------------------------------------------------------------------
  409.  *
  410.  */
  411. void
  412. Fsconsist_IOClientKill(clientList, clientID, refPtr, writePtr, execPtr)
  413.     List_Links *clientList;    /* List of clients to a file. */
  414.     int        clientID;    /* Client to delete. */
  415.     int        *refPtr;    /* Number of times client has file open. */
  416.     int        *writePtr;    /* Number of times client is writing file. */
  417.     int        *execPtr;    /* Number of times clients is executing file.*/
  418. {
  419.     register Fsconsist_ClientInfo     *clientPtr;
  420.  
  421.     *refPtr = 0;
  422.     *writePtr = 0;
  423.     *execPtr = 0;
  424.  
  425.     /*
  426.      * Remove the client from the list of clients using the file.
  427.      */
  428.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  429.     if (clientPtr->clientID == clientID) {
  430.         *refPtr += clientPtr->use.ref;
  431.         *writePtr += clientPtr->use.write;
  432.         *execPtr += clientPtr->use.exec;
  433.         if (clientPtr->locked) {
  434.         clientPtr->use.ref = 0;
  435.         clientPtr->use.write = 0;
  436.         clientPtr->use.exec = 0;
  437.         } else {
  438.         REMOVE_CLIENT(clientPtr);
  439.         }
  440.         break;
  441.     }
  442.     }
  443.  
  444. }
  445.  
  446. /*
  447.  * ----------------------------------------------------------------------------
  448.  *
  449.  * Fsconsist_IOClientStatus --
  450.  *
  451.  *    This computes the difference between a client's version of its
  452.  *    state and our version of the client's usage state.  This is called
  453.  *    during a device reopen to see how the client's state is different.
  454.  *
  455.  * Results:
  456.  *    The client's version of the use state is modified to reflect
  457.  *    the difference between our previous notion of the state and
  458.  *    the client's notion of the state.  This means that the ref, write,
  459.  *    and exec fields can be positive or negative after this call.
  460.  *    If they are zero then the client's state matches ours.
  461.  *    
  462.  * Side effects:
  463.  *    None.
  464.  *
  465.  * ----------------------------------------------------------------------------
  466.  *
  467.  */
  468. void
  469. Fsconsist_IOClientStatus(clientList, clientID, clientUsePtr)
  470.     List_Links *clientList;    /* List of clients to a file. */
  471.     int        clientID;    /* Client to check. */
  472.     Fsio_UseCounts    *clientUsePtr;    /* Client's version of the usage */
  473. {
  474.     register Fsconsist_ClientInfo     *clientPtr;
  475.  
  476.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  477.     if (clientPtr->clientID == clientID) {
  478.         clientUsePtr->ref -= clientPtr->use.ref;
  479.         clientUsePtr->write -= clientPtr->use.write;
  480.         clientUsePtr->exec -= clientPtr->use.exec;
  481.         return;
  482.     }
  483.     }
  484. }
  485.  
  486.  
  487. /*
  488.  * ----------------------------------------------------------------------------
  489.  *
  490.  * Fsconsist_AddClient --
  491.  *
  492.  *      Add a client to the master list of clients that is checked by
  493.  *    Fsconsist_ClientScavenge.
  494.  *
  495.  * Results:
  496.  *    None.
  497.  *
  498.  * Side effects:
  499.  *    May add the client to the list.
  500.  *
  501.  * ----------------------------------------------------------------------------
  502.  *
  503.  */
  504. /*ARGSUSED*/
  505. ENTRY void
  506. Fsconsist_AddClient(clientID)
  507.     int clientID;
  508. {
  509. #ifdef notdef
  510.     register    ClientItem    *listPtr;
  511.  
  512.     LOCK_MONITOR;
  513.  
  514.     LIST_FORALL(masterClientList, (List_Links *)listPtr) {
  515.     if (listPtr->clientID == clientID) {
  516.         goto exit;
  517.     }
  518.     }
  519.     listPtr = mnew(ClientItem);
  520.     listPtr->clientID = clientID;
  521.     List_InitElement((List_Links *)listPtr);
  522.     List_Insert((List_Links *)listPtr, LIST_ATFRONT(masterClientList));
  523. exit:
  524.     UNLOCK_MONITOR;
  525. #endif notdef
  526. }
  527.  
  528.